package org.atovio.structure.matrix;

/**
 * 矩阵类
 *
 * @author AtoVio, Winter Yuan
 * @version 1.0
 */
public class Matrix {

    // 矩阵行号
    private int rows;
    // 矩阵列号
    private int columns;
    // 二维数组，存储矩阵元素
    private int[][] element;
    // 最小容量
    private static final int MIN_CAPACITY = 6;


    /**
     * 构造矩阵
     *
     * @param m 行数
     * @param n 列数
     */
    public Matrix(int m, int n) {
        if (m > 0 && n > 0) {
            this.rows = m;
            this.columns = n;
            if (m < MIN_CAPACITY)
                m = MIN_CAPACITY;
            if (n < MIN_CAPACITY)
                n = MIN_CAPACITY;
            this.element = new int[m][n];
        } else
            throw new IllegalArgumentException("矩阵行列数不能 < 0，m =" + m + ", n = " + n);
    }

    /**
     * 构造n x n的矩阵
     */
    public Matrix(int n) {
        this(n, n);
    }

    /**
     * 构造0x0的矩阵
     */
    public Matrix() {
        this(0, 0);
    }

    /**
     * 构造mxn矩阵，由数组values提供元素
     *
     * @param m     行数
     * @param n     列数
     * @param valus 元素数组
     */
    public Matrix(int m, int n, int[][] valus) {
        this(m, n);
        // value元素不足时补足0，忽略多余元素
        for (int i = 0; i < valus.length && i < m; i++) {
            for (int j = 0; j < valus.length && j < n; j++)
                this.element[i][j] = valus[i][j];
        }
    }

    public int getRows() {
        return rows;
    }

    public int getColumns() {
        return columns;
    }

    /**
     * 返回第i行第j个元素。
     *
     * @param i 行号
     * @param j 列号
     * @return 元素
     */
    public int get(int i, int j) {
       if (i >= 0 && i < this.rows && j > 0 && j < this.columns)
            return this.element[i][j];
        throw new IndexOutOfBoundsException("i=" + i + ", j=" + j);
    }

    /**
     * 设置第i行第j列元素为value
     *
     * @param i     行号
     * @param j     列号
     * @param value 元素值
     */
    public void set(int i, int j, int value) {
        if (i >= 0 && i < this.rows && j > 0 && j < this.columns)
            this.element[i][j] = value;
        throw new IndexOutOfBoundsException("i=" + i + ", j=" + j);
    }

    @Override
    public String toString() {
        StringBuilder str = new StringBuilder(" 矩阵" + this.getClass().getSimpleName() + "(" + this.rows + "x" + this.columns + "): \n");
        for (int i = 0; i < this.columns; i++) {
            for (int j = 0; j < this.columns; j++)
                str.append(String.format("%6d", this.element[i][j]));
            str.append("\n");
        }
        return String.valueOf(str);
    }

    /**
     * 设置矩阵的行列
     * @param m 行数
     * @param n 列数
     */
    public void setRowsColumns(int m, int n) {
        if (m >0 && n >0 ) {
            // 若指定的行列数较大，扩充二维数组
            if (m > this.element.length || n > this.element.length) {
                int[][] source = this.element;
                this.element = new int[m *2][n * 2];
                for (int i = 0; i < this.rows; i++) {
                    for (int j = 0; j < this.columns; j++) {
                        this.element[i][j] = source[i][j];
                    }
                }
            }
            this.rows = m;
            this.columns = n;
        }
        else {
            throw new IllegalArgumentException("行列数不能 < 0, m=" + m+ ", n="+n );
        }
    }
}
